/*
 * 文 件 名:  GenerateUtils.java
 * 版   权: Copyright www.face-garden.com Corporation 2013 版权所有
 * 描     述:  <描述>
 * 修 改 人:  shiwei
 * 修改时间:  2013-8-4
 * 跟踪单号: <跟踪单号>
 * 修改单号: <修改单号>
 * 修改内容: <修改内容>
 */
package sample.utils;

import java.io.File;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import sample.freemarker.FreeMarkerUtils;
import sample.jdbc.JdbcUtils;
import sample.model.GenerateCodeModel;
import sample.model.PropertyModel;
import sample.model.QueryDataBaseModel;
import sample.model.TableModel;

/**
 * <一句话功能简述> <功能详细描述>
 * 
 * @author shiwei
 * @version [版本号, 2013-8-4]
 * @see [相关类/方法]
 * @since [产品/模块版本]
 */

public class GenerateUtils {
	private static final Log logger = LogFactory.getLog(Process.class);

	@SuppressWarnings("finally")
	public static List<Map<String, String>> queryTable(QueryDataBaseModel model) {
		Connection Connection = JdbcUtils.getConnection(model.getUrl(), model.getUserName(), model.getPassWord(),
				model.getDriverName());

		String sql = "select DISTINCT a.TABLE_COMMENT,a.TABLE_NAME from information_schema.TABLES a,INFORMATION_SCHEMA.Columns b where a.TABLE_SCHEMA='"
				+ model.getDatabase() + "' and a.TABLE_NAME=b.TABLE_NAME and a.TABLE_SCHEMA=b.TABLE_SCHEMA";

		if (model.getDriverName().startsWith("oracle.jdbc")) {

			sql = "select table_name TABLE_COMMENT,table_name TABLE_NAME from user_tables";
		}

		PreparedStatement ps = null;
		ResultSet rs = null;
		List<Map<String, String>> list = new ArrayList<Map<String, String>>();
		try {
			ps = Connection.prepareStatement(sql);
			rs = ps.executeQuery();

			while (rs.next()) {
				Map<String, String> map = new HashMap<String, String>();
				map.put("id", rs.getString("TABLE_NAME") + "#" + rs.getString("TABLE_COMMENT"));
				map.put("value", rs.getString("TABLE_NAME"));

				list.add(map);
			}
		} catch (Exception e) {
			logger.error("",e);
			throw e;
		} finally {
			JdbcUtils.close(rs, ps, Connection);
			return list;
		}
	}

	public static void generateCode(GenerateCodeModel model) throws Exception {
		Connection Connection = JdbcUtils.getConnection(model.getUrl(), model.getUserName(), model.getPassWord(),
				model.getDriverName());
		Map<String, Object> map = new HashMap<String, Object>(150);
		SimpleDateFormat simpledateformat = new SimpleDateFormat("yyyy-MM-dd");
		map.put("projectName", model.getProjectName());
		map.put("dateTime", simpledateformat.format(new Date()));
		map.put("module", model.getModule());
		map.put("outPath", model.getOutPath());
		map.put("company", model.getCompany());
		map.put("codeType", model.getCodeType());
		SimpleDateFormat simpleyearformat = new SimpleDateFormat("yyyy");
		map.put("dateYear", simpleyearformat.format(new Date()));

		CommonMap.setCommonMap(map);

		String module_tabs = model.getTables();

		try {
			module_tabs = URLDecoder.decode(module_tabs, "UTF-8");
		} catch (UnsupportedEncodingException e1) {
			logger.error("",e1);
			throw e1;
		}

		String[] tabs = module_tabs.split(",");
		int count = 0;
		List<Map<String, Object>> tables = new ArrayList<Map<String, Object>>();
		for (String tablenames : tabs) {
			String[] tabDescs = tablenames.split("#");
			String tablename = tabDescs[0];
			String tableComment = "";
			if (tabDescs.length > 1)
				tableComment = tabDescs[1];
			// 一个表一个表生成代码
			Map<String, Object> table = new HashMap<String, Object>();
			StringBuffer sql = new StringBuffer();
			sql.append(
					"select COLUMN_NAME,DATA_TYPE,COLUMN_COMMENT,CHARACTER_MAXIMUM_LENGTH,COLUMN_KEY from INFORMATION_SCHEMA.Columns where table_name ='");
			sql.append(tablename).append("' and table_schema='").append(model.getDatabase()).append("'");

			if (model.getDriverName().startsWith("oracle.jdbc")) {

				sql = new StringBuffer(
						"select lower(t1.column_name) column_name,lower(data_type) data_type ,user_col_comments.COMMENTS COLUMN_COMMENT,data_length CHARACTER_MAXIMUM_LENGTH,case when t2.constraint_name is not null then 'PRI' else ' ' end  COLUMN_KEY from user_tab_columns t1 left join (select a.constraint_name,  a.column_name, a.table_name  from user_cons_columns a, user_constraints b  where a.constraint_name = b.constraint_name  and b.constraint_type = 'P') t2  on t1.COLUMN_NAME=t2.COLUMN_NAME and t1.table_name=t2.table_name left join user_col_comments on user_col_comments.TABLE_NAME=t1.TABLE_NAME and user_col_comments.column_name=t1.COLUMN_NAME where t1.table_name='")
								.append(tablename).append("'");
			}
			PreparedStatement ps = null;
			ResultSet rs = null;

			try {
				ps = Connection.prepareStatement(sql.toString());
				if (ps.execute()) {
					rs = ps.getResultSet();
				}
				List<TableModel> list = new ArrayList<TableModel>();
				int num = 0;
				int t_num = 0;
				boolean flag = false;// 是否为树结构表
				boolean flagName = false;
				while (rs.next()) {
					TableModel TableModel = new TableModel();
					TableModel.setTableComment("");

					if (rs.getString("COLUMN_KEY").toUpperCase().equals("PRI")) {
						TableModel.setKey(1);
					} else {
						TableModel.setKey(0);
					}
					String columnName = rs.getString("COLUMN_NAME").toUpperCase();
					if (rs.getString("COLUMN_NAME").toUpperCase().equals("PARENTID")) {
						flag = true;
					}
					if (rs.getString("COLUMN_NAME").toUpperCase().equals("NAME")) {
						flagName = true;
					}
					if (rs.getString("COLUMN_NAME").toUpperCase().equals("ID")) {
						TableModel.setIsId(1);
					} else {
						TableModel.setIsId(0);
					}
					if (rs.getString("COLUMN_NAME").toUpperCase().equals("CREATE_TIME")) {
						TableModel.setIsCreateTime(1);
					} else {
						TableModel.setIsCreateTime(0);
					}
					if (rs.getString("COLUMN_NAME").toUpperCase().equals("UPDATE_TIME")) {
						TableModel.setIsUpdateTime(1);
					} else {
						TableModel.setIsUpdateTime(0);
					}
					if (rs.getString("COLUMN_NAME").toUpperCase().equals("UPDATE_BY")) {
						TableModel.setIsUpdateBy(1);
					} else {
						TableModel.setIsUpdateBy(0);
					}
					if (rs.getString("COLUMN_NAME").toUpperCase().equals("CREATE_BY")) {
						TableModel.setIsCreateBy(1);
					} else {
						TableModel.setIsCreateBy(0);
					}
					if (rs.getString("COLUMN_NAME").toUpperCase().equals("OPT_TIME")) {
						TableModel.setIsOptTime(1);
					} else {
						TableModel.setIsOptTime(0);
					}

					if (!rs.getString("COLUMN_NAME").toUpperCase().equals("UPDATE_BY")
							&& !rs.getString("COLUMN_NAME").toUpperCase().equals("UPDATE_TIME")
							&& !rs.getString("COLUMN_NAME").toUpperCase().equals("CREATE_TIME")
							&& !rs.getString("COLUMN_NAME").toUpperCase().equals("ID")
							&& !rs.getString("COLUMN_NAME").toUpperCase().equals("CREATE_BY")
							&& !rs.getString("COLUMN_NAME").toUpperCase().equals("OPT_TIME")) {
						TableModel.setIsDto(1);
						t_num++;
					}

					TableModel.setColumn(rs.getString("COLUMN_NAME"));
					// 字段注释用#分割#前的为字段含义，#后面为字段的标注 第二个位置为下拉列表数据（1:分类;2:品牌）
					String colComment = rs.getString("COLUMN_COMMENT");
					if (!StringUtils.isEmpty(colComment) && colComment.indexOf("#") != -1) {
						String[] strs = colComment.split("#");
						TableModel.setColumnComment(strs[0]);
						if (strs.length > 1) {
							List<PropertyModel> selectedAttr = new ArrayList<PropertyModel>();
							String[] strs1 = strs[1].split(";");
							PropertyModel propertyModel = null;
							for (String string : strs1) {
								if (!StringUtils.isEmpty(string)) {
									String[] strs2 = string.split(":");
									if (strs2.length > 1) {
										propertyModel = new PropertyModel();
										propertyModel.setId(strs2[0].trim());
										propertyModel.setValue(strs2[1].trim());

										selectedAttr.add(propertyModel);
									}
								}
							}
							if (!selectedAttr.isEmpty()) {
								TableModel.setSelectedAttr(selectedAttr);
								TableModel.setIsSelected(1);
							}
						}
					} else {
						TableModel.setColumnComment(rs.getString("COLUMN_COMMENT"));
					}
					String data_type = rs.getString("DATA_TYPE");
					String[] property_ = rs.getString("COLUMN_NAME").split("_");

					if (property_.length > 1) {
						if (property_.length == 2) {
							TableModel
									.setProperty(property_[0].toLowerCase() + property_[1].substring(0, 1).toUpperCase()
											+ property_[1].substring(1).toLowerCase());
							TableModel.setPropertyBig(
									property_[0].substring(0, 1).toUpperCase() + property_[0].substring(1).toLowerCase()
											+ property_[1].substring(0, 1).toUpperCase()
											+ property_[1].substring(1).toLowerCase());
						} else {
							TableModel
									.setProperty(property_[0].toLowerCase() + property_[1].substring(0, 1).toUpperCase()
											+ property_[1].substring(1).toLowerCase()
											+ property_[2].substring(0, 1).toUpperCase()
											+ property_[2].substring(1).toLowerCase());
							TableModel.setPropertyBig(
									property_[0].substring(0, 1).toUpperCase() + property_[0].substring(1).toLowerCase()
											+ property_[1].substring(0, 1).toUpperCase()
											+ property_[1].substring(1).toLowerCase()
											+ property_[2].substring(0, 1).toUpperCase()
											+ property_[2].substring(1).toLowerCase());
						}
					} else {
						TableModel.setProperty(property_[0].toLowerCase());
						TableModel.setPropertyBig(
								property_[0].substring(0, 1).toUpperCase() + property_[0].substring(1).toLowerCase());
					}
					TableModel.setProperty1("#{" + TableModel.getProperty() + "}");
					TableModel.setPropertyItem("#{item." + TableModel.getProperty() + "}");
					TableModel.setProperty2("#" + TableModel.getProperty());
					TableModel.setProperty5("${ " + TableModel.getProperty() + "?default('')}");
					TableModel.setProperty6("row." + TableModel.getProperty());
					// data_type=data_type.toLowerCase();
					if (data_type.startsWith("int") || data_type.startsWith("integer") || data_type.startsWith("bigint")
							|| data_type.startsWith("long")) {
						TableModel.setJavaType("java.lang.Long");
						TableModel.setJavaTypeShort("Long");
						TableModel.setProperty3("${" + TableModel.getProperty() + "?c}");
						TableModel.setProperty4("${row." + TableModel.getProperty() + "?c}");

						TableModel.setCharLength(0);
					} else if (data_type.equals("decimal") || data_type.startsWith("double")
							|| data_type.startsWith("float") || data_type.startsWith("number")) {
						TableModel.setJavaType("java.lang.Double");
						TableModel.setJavaTypeShort("Double");
						TableModel.setProperty3("${" + TableModel.getProperty() + "?default('')}");
						TableModel.setProperty4("${row." + TableModel.getProperty() + "?default('')}");
					} else if (data_type.startsWith("varchar")) {
						TableModel.setJavaType("java.lang.String");
						TableModel.setJavaTypeShort("String");
						TableModel.setProperty3("${" + TableModel.getProperty() + "?default('')}");
						TableModel.setProperty4("${row." + TableModel.getProperty() + "?default('')}");

						TableModel.setCharLength(rs.getInt("CHARACTER_MAXIMUM_LENGTH"));
					} else if (data_type.equals("date")) {
						TableModel.setJavaType("java.util.Date");
						TableModel.setJavaTypeShort("Date");
						TableModel.setProperty3("${" + TableModel.getProperty() + "?default('')}");
						TableModel.setProperty4("${row." + TableModel.getProperty() + "?default('')}");
					} else if (data_type.equals("datetime") || data_type.startsWith("timestamp")) {
						TableModel.setJavaType("java.util.Date");
						TableModel.setJavaTypeShort("Date");
						TableModel.setProperty3("${" + TableModel.getProperty() + "?default('')}");
						TableModel.setProperty4("${row." + TableModel.getProperty() + "?default('')}");
					} else if (data_type.equals("text")) {
						TableModel.setJavaType("java.lang.String");
						TableModel.setJavaTypeShort("String");
						TableModel.setProperty3("${" + TableModel.getProperty() + "?default('')}");
						TableModel.setProperty4("${row." + TableModel.getProperty() + "?default('')}");

						TableModel.setCharLength(0);
					} else if (data_type.equals("timestamp")) {
						TableModel.setJavaType("java.sql.Timestamp");
						TableModel.setJavaTypeShort("Timestamp");
						TableModel.setProperty3("${" + TableModel.getProperty() + "?default('')}");
						TableModel.setProperty4("${row." + TableModel.getProperty() + "?default('')}");

						TableModel.setCharLength(0);
					} else {
						TableModel.setJavaType("java.lang.String");
						TableModel.setJavaTypeShort("String");
						TableModel.setProperty3("${" + TableModel.getProperty() + "?default('')}");
						TableModel.setProperty4("${row." + TableModel.getProperty() + "?default('')}");

						TableModel.setCharLength(0);
					}
					list.add(TableModel);

					num++;
				}
				map.put("insertNum", num - t_num + 1);
				map.put("tableNameDb", tablename);
				String[] temp = tablename.split("_");

				if (temp.length == 3) {
					map.put("tableName",
							temp[0].substring(0, 1).toUpperCase() + temp[0].substring(1).toLowerCase()
									+ temp[1].substring(0, 1).toUpperCase() + temp[1].substring(1).toLowerCase()
									+ temp[2].substring(0, 1).toUpperCase() + temp[2].substring(1).toLowerCase());
					map.put("tableNameMin",
							temp[0].toLowerCase() + temp[1].substring(0, 1).toUpperCase()
									+ temp[1].substring(1).toLowerCase() + temp[2].substring(0, 1).toUpperCase()
									+ temp[2].substring(1).toLowerCase());

				} else if (temp.length > 3) {
					StringBuffer sb = new StringBuffer();

					for (int i = 0; i < temp.length; i++) {
						sb.append(temp[i].substring(0, 1).toUpperCase());
						sb.append(temp[i].substring(1).toLowerCase());
					}
					map.put("tableName", sb.toString());
					sb.delete(0, sb.length());
					for (int i = 0; i < temp.length; i++) {
						if (i == 0) {
							sb.append(temp[0].toLowerCase());
						} else {
							sb.append(temp[i].substring(0, 1).toUpperCase());
							sb.append(temp[i].substring(1).toLowerCase());
						}
					}

					map.put("tableNameMin", sb.toString());
				} else if (temp.length == 2) {
					map.put("tableName", temp[0].substring(0, 1).toUpperCase() + temp[0].substring(1).toLowerCase()
							+ temp[1].substring(0, 1).toUpperCase() + temp[1].substring(1).toLowerCase());
					map.put("tableNameMin", temp[0].toLowerCase() + temp[1].substring(0, 1).toUpperCase()
							+ temp[1].substring(1).toLowerCase());
				} else if (temp.length == 1) {
					map.put("tableName", temp[0].substring(0, 1).toUpperCase() + temp[0].substring(1).toLowerCase());
					map.put("tableNameMin", temp[0].toLowerCase());
				}

				map.put("treeflag", "");
				// 如果为树形结构
				if (flag) {
					map.put("treeflag", "1");
					map.put("dto.parentid", "${dto.parentid}");
					map.put("item.id", "${item.id}");// ${menuTreeDTO.parentid}
														// ${menuTreeDTO.title}
					map.put("dto.id", "${dto.id}");

					if (flagName) {
						map.put("item.title", "${item.name}");
						map.put("dto.title", "${dto.title}");
						map.put("dto.name", "${dto.name}");
					} else {
						map.put("item.title", "${item.title}");
						map.put("dto.title", "${dto.title}");
					}
				}

				map.put("tableAttrs", list);
				map.put("createSTime", "${createSTime?default('')}");
				map.put("createETime", "${createETime?default('')}");
				map.put("updateSTime", "${updateSTime?default('')}");
				map.put("updateETime", "${updateETime?default('')}");
				map.put("createSTime1", "#{createSTime}");
				map.put("createETime1", "#{createETime}");
				map.put("updateSTime1", "#{updateSTime}");
				map.put("updateETime1", "#{updateETime}");
				map.put("id", "#{id}");
				map.put("item", "#{item}");
				map.put("pageIndex", "#{pageIndex}");
				map.put("pageSize", "#{pageSize}");

				// 读取文件

				File f1 = new File(model.getCodetemplatePath() + File.separator + "codetemplate");
				table.put("tableName", map.get("tableName"));
				tables.add(table);
				if (count == (tabs.length - 1)) {
					map.put("tables", tables);
				}

				if (tablename.indexOf("rel") != -1) {
					map.put("isRel", 1);
				} else {
					map.put("isRel", 0);
				}

				findFile(f1, map);

			} catch (Exception e) {
				logger.error("",e);
				throw e;
			} finally {
				JdbcUtils.close(rs, ps, Connection);
			}
			count++;
		}
	}

	public static void findFile(File f, Map<String, Object> dataMap) throws Exception {
		if (f == null) {
			return;
		}
		if (f.isFile()) {
			FreeMarkerUtils.generate(f, dataMap);
		} else {
			File[] fs = f.listFiles();
			for (File file : fs) {
				findFile(file, dataMap);
			}
		}
	}
}
